package com.goldmantis.alitrip.common.mongodb;


import com.mongodb.*;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import com.mongodb.client.model.Filters;
import com.mongodb.client.result.DeleteResult;
import org.apache.commons.lang3.StringUtils;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class MongoService {

    private static volatile MongoClient mongoClient;


    @Value("${systemId}")
    private Long systemId;

    @Value("${mongo.host}")
    private String host;

    @Value("${mongo.port}")
    private Integer port;

    @Value("${mongo.user}")
    private String user;

    @Value("${mongo.password}")
    private String password;

    @Value("${mongo.authDataBase}")
    private String authDataBase;


    public MongoClient getInstance()  {

        if(null==mongoClient) {
            synchronized (MongoService.class){
                if(null==mongoClient){
                    List<ServerAddress> serverAddrList = new ArrayList<>();
                    ServerAddress serverAddress = new ServerAddress(host,port);
                    serverAddrList.add(serverAddress);

                    List<MongoCredential> credentialList = new ArrayList<>();
                    MongoCredential credential = MongoCredential.createScramSha1Credential(user, authDataBase, password.toCharArray());
                    credentialList.add(credential);

                    mongoClient = new MongoClient(serverAddrList, credentialList);
                    return mongoClient;
                }
            }
        }
        return mongoClient;

    }


    /**
     * 获取数据库对象
     * @param databaseName 数据库名称
     * @return
     */
    public MongoDatabase getDataBase(String databaseName){
        if(StringUtils.isNotBlank(databaseName)&&!StringUtils.EMPTY.equals(databaseName)){
            MongoDatabase database = getInstance().getDatabase(databaseName);
            return database;
        }
        return null;
    }

    /**
     * 根据数据库和集合名称获取集合文档
     * @param dataBaseName 数据库名称
     * @param collectionName 文档内容
     * @return
     * @throws Exception
     */
    public MongoCollection<Document> getCollection(String dataBaseName,String collectionName) throws Exception {
        if(StringUtils.isBlank(dataBaseName)){
            throw new Exception("database name 不能为空！");
        }
        if(StringUtils.isBlank(collectionName)){
            throw new Exception("collection name不能为空！");
        }

        MongoCollection<Document> collection = getInstance().getDatabase(dataBaseName).getCollection(collectionName);
        return collection;
    }

    /**
     *
     * @param dataBaseName 数据库名称
     * @return 集合名称
     */
    public List<String> getAllCollections(String dataBaseName) {
        MongoIterable<String> colls = getInstance().getDatabase(dataBaseName).listCollectionNames();
        List<String> list = new ArrayList<String>();
        for (String s : colls) {
            list.add(s);
        }
        return list;
    }

    /**
     * 获取全部数据库名称
     * @return 数据库列表
     */
    public MongoIterable<String> getAllDataBaseNames() {
        MongoIterable<String> databaseNames = getInstance().listDatabaseNames();
        return databaseNames;
    }

    /**
     * 删除数据库
     * @param dataBaseName 数据库名称
     */
    public void dropDataBase(String dataBaseName){
        this.getDataBase(dataBaseName).drop();
    }


    /**
     * 根据Id查询
     * @param dataBaseName
     * @param collectionName
     * @param id
     * @return
     * @throws Exception
     */
    public Document selectById(String dataBaseName, String collectionName,String id) throws Exception {
        MongoCollection<Document> collection = getCollection(dataBaseName, collectionName);

        ObjectId objectId=new ObjectId(id);
        Document first = collection.find(Filters.eq("_id", objectId)).first();
        return first;
    }

    /**
     * 根据Id查询
     * @param collections
     * @param id
     * @return
     */
    public Document selectById(MongoCollection<Document> collections,String id){
        return collections.find(Filters.eq("_id",id)).first();
    }

    /**
     * 获取数量
     * @param collection
     * @return
     */
    public long getCount(MongoCollection<Document> collection){
        long count = collection.count();
        return count;
    }

    /**
     * 条件查询
     * @param collection
     * @param filter
     * @return
     */
    public MongoCursor<Document> find(MongoCollection<Document> collection, Bson filter) {
        return collection.find(filter).iterator();
    }

    /**
     * 分页查询
     * @param collection
     * @param filter
     * @param offset
     * @param limit
     * @return
     */
    public MongoCursor<Document> findByPage(MongoCollection<Document> collection, Bson filter, int offset, int limit) {
        Bson orderBy = new BasicDBObject("_id", 1);
        return collection.find(filter).sort(orderBy).skip((offset - 1) * limit).limit(limit).iterator();
    }

    /**
     * 通过Id删除
     * @param collection
     * @param id
     * @return
     */
    public int deleteById(MongoCollection<Document> collection, String id) {
        int count = 0;
        ObjectId _id = new ObjectId(id);
        Bson filter = Filters.eq("_id", _id);
        DeleteResult deleteResult = collection.deleteOne(filter);
        count = (int) deleteResult.getDeletedCount();
        return count;
    }

    /**
     *
     * @param collection
     * @param id
     * @param newdoc
     * @return
     */
    public Document updateById(MongoCollection<Document> collection, String id, Document newdoc) {
        ObjectId _id = new ObjectId(id);
        Bson filter = Filters.eq("_id", _id);
        // coll.replaceOne(filter, newdoc); // 完全替代
        collection.updateOne(filter, new Document("$set", newdoc));
        return newdoc;
    }

    public void dropCollection(String dbName, String collName) {
        getDataBase(dbName).getCollection(collName).drop();
    }

    /**
     * 关闭Mongodb
     */
    public void close() {
        if (mongoClient != null) {
            mongoClient.close();
            mongoClient = null;
        }

    }










}
